/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.test.gwt.tests;

import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Label;

import fr.openparts.OpenParts.client.OPPartContainer;

/**
 * GWT tests for OPPartContainer.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 24 January 2010
 */
public class OPPartContainerTestGwt extends GWTTestCase {

    private static final String SLOT_ID = "dummySlotId";
    
    /**
     * Return the name of the tested GWT Module.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
     */
    @Override
    public final String getModuleName() {
        return "fr.openparts.OpenParts.test.gwt.TestOpenParts";
    }
    
    /**
     * Test getting a container for the given existing slot. Should get something not null.
     */
    public final void testGetContainer() {
        final Document doc = Document.get();
        final DivElement slot = doc.createDivElement();
        slot.setId(SLOT_ID);
        doc.insertFirst(slot);
        assertNotNull("Container should not be null", OPPartContainer.get(SLOT_ID));
        doc.removeChild(slot);
    }
    
    /**
     * Test getting a container for an inexistant slot. Should get null.
     */
    public final void testGetContainerInexistantSlot() {
        assertNull("Should get a null container", OPPartContainer.get(SLOT_ID));
    }
    
    /**
     * Test getting a container for a null slot id. Should raise an assertion error.
     */
    public final void testGetContainerNullSlotId() {
        if (assertionsAreEnabled()) {
            try {
                OPPartContainer.get(null);
                fail("OPPartContainer should raise an assertion error when asking for a container with a null slot id.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test adding a widget. Should get only one children, the added widget.
     */
    public final void testAddingAWidget() {
        final Document doc = Document.get();
        final DivElement slot = doc.createDivElement();
        slot.setId(SLOT_ID);
        doc.insertFirst(slot);
        
        final OPPartContainer container = OPPartContainer.get(SLOT_ID);
        final Element containerElement = container.getElement();
        
        assertFalse("container should not contains any children yet", containerElement.hasChildNodes());

        container.add(new Label("View"));
        
        assertTrue("container should contains one child now", containerElement.hasChildNodes());
        assertEquals("container should contains one and only one child", 1, containerElement.getChildCount());
        assertTrue("container child should be \"View\"", containerElement.getFirstChildElement().getInnerHTML().contains("View"));
        
        doc.removeChild(slot);
    }
    
    /**
     * Test adding a widget when the element (slot) already have a child ("loading..." widget). Should still get only one children, the added widget.
     */
    public final void testAddingAWidgetWhenThereIsAlreadyAChild() {
        final Document doc = Document.get();
        final DivElement slot = doc.createDivElement();
        slot.setId(SLOT_ID);
        final DivElement loadingWidget = doc.createDivElement();
        loadingWidget.setInnerText("Loading...");
        slot.appendChild(loadingWidget);
        doc.insertFirst(slot);
        
        final OPPartContainer container = OPPartContainer.get(SLOT_ID);
        final Element containerElement = container.getElement();
        
        assertTrue("container should already contains a child", containerElement.hasChildNodes());
        assertEquals("container should contains one and only one child", 1, containerElement.getChildCount());
        assertTrue("container child should be \"Loading...\"", containerElement.getFirstChildElement().getInnerHTML().contains("Loading..."));

        container.add(new Label("View"));
        
        assertTrue("container should still contains one child now", containerElement.hasChildNodes());
        assertEquals("container should contains one and only one child", 1, containerElement.getChildCount());
        assertTrue("container child should be \"View\"", containerElement.getFirstChildElement().getInnerHTML().contains("View"));
        
        doc.removeChild(slot);
    }
    
    /**
     * Test adding a null widget. Should raise an assertion error.
     */
    public final void testAddingNullWidget() {
        final Document doc = Document.get();
        final DivElement slot = doc.createDivElement();
        slot.setId(SLOT_ID);
        doc.insertFirst(slot);
        
        final OPPartContainer container = OPPartContainer.get(SLOT_ID);
        
        if (assertionsAreEnabled()) {
            try {
                container.add(null);
                fail("OPPartContainer should raise an assertion error when adding a null widget.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
        
        doc.removeChild(slot);
    }
    
    /**
     * Check if assertions are enabled.
     * 
     * @return true if assertions are enabled, false otherwise
     */
    private final boolean assertionsAreEnabled() {
        try {
            assert false;
            return false;
        } catch (AssertionError e) {
            return true;
        }
    }
}
